package model

import (
	"context"
	"errors"
	"github.com/jinzhu/copier"
	"github.com/zeromicro/go-zero/core/stores/mon"
	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/bson/primitive"
	"go.mongodb.org/mongo-driver/mongo"
	"large-model-platform-backend/internal/types"
)

var _ UserModel = (*customUserModel)(nil)

type (
	// UserModel is an interface to be customized, add more methods here,
	// and implement the added methods in customUserModel.
	UserModel interface {
		userModel
		FindAll(ctx context.Context) ([]User, error)
		UpdateOther(ctx context.Context, id string, user *User) error
		InsertChatSession(ctx context.Context, data *types.ChatSessionReq) (*mongo.UpdateResult, error)
		DeleteChatSession(ctx context.Context, data *types.ChatSessionReq) (*mongo.UpdateResult, error)
	}

	customUserModel struct {
		*defaultUserModel
	}
)

func (c customUserModel) UpdateOther(ctx context.Context, id string, user *User) error {
	oid, err := primitive.ObjectIDFromHex(id)
	if err != nil {
		return ErrInvalidObjectId
	}
	common := UserCommon{}
	copier.Copy(&common, user)
	_, err = c.conn.UpdateOne(ctx, bson.D{{"_id", oid}}, bson.M{"$set": common})
	return err
}

func (c customUserModel) InsertChatSession(ctx context.Context, data *types.ChatSessionReq) (*mongo.UpdateResult, error) {
	conn := c.conn
	id, err := primitive.ObjectIDFromHex(data.UserId)
	if err != nil {
		return nil, ErrInvalidObjectId
	}
	var user []types.UserData
	err = conn.Find(ctx, &user, bson.D{
		{"_id", id},
		//{"chatSessions.name", data.Name},
	})
	if err != nil {
		return nil, err
	}
	//todo 注意 如果 一开始插入数据的时候，没有全部字段都插入，则为空的字段数据类型就会默认string
	if len(user) != 0 {
		u := user[0]
		sessions := u.ChatSessions
		if len(sessions) == 0 {
			one, err := conn.UpdateOne(ctx, bson.D{
				{"_id", id},
			}, bson.D{
				{"$set", bson.D{{"chatSessions", []types.ChatSession{
					types.ChatSession{Name: data.Name},
				}}}},
			})
			if err != nil {
				return nil, err
			}
			return one, err
		} else {
			for _, session := range sessions {
				if session.Name == data.Name {
					return nil, errors.New("chatSession is exist")
				}
			}
			one, err := conn.UpdateOne(ctx, bson.D{
				{"_id", id},
			}, bson.D{
				{"$push", bson.D{{"chatSessions", types.ChatSession{Name: data.Name}}}},
			})
			if err != nil {
				return nil, err
			}
			return one, err
		}

	} else {
		//return nil, errors.New("chatSession is exist")
		return nil, errors.New("user is not exist")
	}
}

func (c customUserModel) DeleteChatSession(ctx context.Context, data *types.ChatSessionReq) (*mongo.UpdateResult, error) {
	conn := c.conn
	id, err := primitive.ObjectIDFromHex(data.UserId)
	if err != nil {
		return nil, ErrInvalidObjectId
	}
	// 要删除对象数组中的特定元素，可以使用update操作和 $pull 操作符。$pull 操作符从数组中删除与指定条件匹配的所有元素
	// 在这个示例中，我们使用update操作指定了要更新的文档条件和更新操作。"$pull"操作符指定了要从数组中删除的元素条件。这条命令将删除_id为1的文档中phoneNumbers数组中type为work的对象。
	one, err := conn.UpdateOne(ctx, bson.D{
		{"_id", id},
	}, bson.D{
		{"$pull", bson.D{{"chatSessions", bson.D{{"name", data.Name}}}}},
	})
	if err != nil {
		return nil, err
	}
	return one, err
}

func (c customUserModel) FindAll(ctx context.Context) ([]User, error) {
	var users []User
	err := c.conn.Find(ctx, &users, bson.D{})
	return users, err
}

// NewUserModel returns a model for the mongo.
func NewUserModel(url, db, collection string) UserModel {
	conn := mon.MustNewModel(url, db, collection)
	return &customUserModel{
		defaultUserModel: newDefaultUserModel(conn),
	}
}
